package com.yang.service.Impl;

import com.alibaba.fastjson.JSON;
import com.yang.entity.Category;
import com.yang.entity.commodityDetail.CarouselImages;
import com.yang.entity.commodityDetail.Detail;
import com.yang.entity.commodityDetail.Skus;
import com.yang.entity.commodityDetail.Specs;
import com.yang.mapper.CommodityMapper;
import com.yang.entity.Commodity;
import com.yang.service.CommodityService;
import jakarta.annotation.Resource;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;


@Service
public class CommodityImpl implements CommodityService {

    @Resource
    private CommodityMapper commodityMapper;

    @Resource
    private MongoTemplate mongoTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public List<Commodity> getCommodityList(Integer pageNum, Integer pageSize, Integer categoryId) {
        // 页数和每页显示条数
//        if (pageSize == null) pageSize = 12;
        // 缓存key
        String key = "commodity";
        if (categoryId != 0) {
            key = "category" + "_" + categoryId;
        } else {
            categoryId = null;
        }
        // 结果集
        List<Commodity> result = null;
        // 从redis中获取商品列表
        String resultJson = (String) redisTemplate.opsForHash().get(key, pageNum.toString());
        // 获取指定key中第一个元素
        String firstPageJson = (String) redisTemplate.opsForHash().get(key, "1");
        // 判断key是否存在（是否失效）
        if (resultJson == null && firstPageJson == null) {
            // 从数据库中获取商品列表
            List<Commodity> commodityList = commodityMapper.getCommodityList(categoryId);
            // 将商品列表每隔12个元素存入redis中
            int hashKey = 1;
            for (int i = 0; i < commodityList.size(); i += 12) {
                int end = i + 12;
                if (end > commodityList.size()) end = commodityList.size();
                String subListJson = JSON.toJSONString(commodityList.subList(i, end));
                redisTemplate.opsForHash().putAll(key, Collections.singletonMap(String.valueOf(hashKey), subListJson));
                // 为刚存入的商品列表设置过期时间 10分钟, 防止缓存穿透
                hashKey++;
            }
            redisTemplate.expire(key, 1, TimeUnit.DAYS);
        }
        // 如果页码超出范围
        else if (resultJson == null && firstPageJson != null) {
            return null;
        }
        // 当key存在且页码在缓存中
        resultJson = (String) redisTemplate.opsForHash().get(key, pageNum.toString());
        if (resultJson != null) {
            result = JSON.parseArray(resultJson).toJavaList(Commodity.class);
        }
        return result;
    }

    @Override
    public List<Category> getCategoryList() {
        List<Category> categoryList;
        // 从redis中获取分类数据
        String categoryListJson = (String) redisTemplate.opsForValue().get("categoryList");
        // 判断redis中是否有分类数据缓存
        if (categoryListJson != null) {
            categoryList = JSON.parseArray(categoryListJson).toJavaList(Category.class);
        } else {
            // 将分类数据存入redis中
            categoryList = commodityMapper.getCategoryList();
            categoryListJson = JSON.toJSONString(categoryList);
            redisTemplate.opsForValue().set("categoryList", categoryListJson);
        }
        return categoryList;
    }

    @Override
    public Detail getDetailById(Long commodityId) {
        Detail detail = new Detail();
        // mysql获取商品详情数据
        detail.setCommodity(commodityMapper.getCommodityById(commodityId));
        // mongoDB获取商品规格数据
        Query query = new Query(Criteria.where("commodityId").is(commodityId));
        detail.setSkus(mongoTemplate.find(query, Skus.class));
        detail.setSpecs(mongoTemplate.find(query, Specs.class));
        // 获取商品轮播图图片url
        detail.setImages(mongoTemplate.find(query, CarouselImages.class).getFirst().getImgUrl());
        return detail;
    }

    @Override
    public List<Commodity> getSearchCommodity(Integer pageNum, Integer pageSize, String keyword) {
        //结果集
        List<Commodity> result = null;
        // 页数和每页显示条数
        if (pageNum == null) pageNum = 1;
        // if (pageSize == null) pageSize = 12;
        String key = "search_" + keyword;
        // 从redis中获取商品列表
        String resultJson = (String) redisTemplate.opsForHash().get(key, pageNum.toString());
        String keywordFirst = (String) redisTemplate.opsForHash().get(key, "1");
        // 判断redis中是否有商品列表缓存
        if (resultJson == null && keywordFirst == null) {
            // 从数据库中获取商品列表
            List<Commodity> commodityList = commodityMapper.getSearchCommodity(keyword);
            // 将商品列表每隔12个元素存入redis中
            int hashKey = 1;
            for (int i = 0; i < commodityList.size(); i += 12) {
                int end = i + 12;
                if (end > commodityList.size()) end = commodityList.size();
                String subListJson = JSON.toJSONString(commodityList.subList(i, end));
                redisTemplate.opsForHash().putAll(key, Collections.singletonMap(String.valueOf(hashKey), subListJson));
                // 为刚存入的商品列表设置过期时间 10分钟, 防止缓存穿透
                hashKey++;
            }
            redisTemplate.expire(key, 10, TimeUnit.MINUTES);
        }
        // 页码超出范围
        else if (resultJson == null && keywordFirst != null) {
            return null;
        }
        resultJson = (String) redisTemplate.opsForHash().get(key, pageNum.toString());
        // 如果结果不为空
        if (resultJson != null) {
            result = JSON.parseArray(resultJson).toJavaList(Commodity.class);
        }
        return result;
    }
}
